package org.yelongframework.zip.ant.executor;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.List;
import java.util.function.Function;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.tools.zip.ZipOutputStream;
import org.yelongframework.commons.io.FileUtil;
import org.yelongframework.core.util.function.io.ByteArraySupplier;
import org.yelongframework.zip.entry.DirZipEntry;
import org.yelongframework.zip.entry.FileZipEntry;
import org.yelongframework.zip.entry.ZipEntry;
import org.yelongframework.zip.file.ReadZipFile;
import org.yelongframework.zip.file.WriteZipFile;

/**
 * 默认实现
 * 
 * @since 1.0.0
 */
public class DefaultAntZipExecutor extends AbstractAntZipExecutor {

	// ==================================================编码==================================================

	public DefaultAntZipExecutor() {
		this("GBK");
	}

	/**
	 * @param encoding 编码
	 */
	public DefaultAntZipExecutor(String encoding) {
		super(encoding);
	}

	// ==================================================压缩==================================================

	@Override
	public void zip(WriteZipFile writeZipFile, OutputStream outputStream) throws IOException {
		ZipOutputStream zipOutputStream = buildZipOutputStream(outputStream);
		List<ZipEntry> zipEntrys = writeZipFile.getZipEntrys();
		for (ZipEntry zipEntry : zipEntrys) {
			String name = zipEntry.getName();
			if (zipEntry.isDirectory()) {
				// 结尾以 / 视为文件夹
				zipOutputStream.putNextEntry(new org.apache.tools.zip.ZipEntry(name + "/"));
			} else if (zipEntry.isFile()) {
				zipOutputStream.putNextEntry(new org.apache.tools.zip.ZipEntry(name));
				ByteArraySupplier dataSource = zipEntry.getDataSource();
				if (null == dataSource) {
					continue;
				}
				byte[] data = dataSource.get();
				if (null == data) {
					continue;
				}
				zipOutputStream.write(data, 0, data.length);
			}
		}
		zipOutputStream.close();
	}

	// ==================================================解压缩==================================================

	@Override
	public void unzip(File file, Function<String, String> unZipFileNameFuction) throws IOException {
		ReadZipFile readZipFile = readZipFile(file);
		List<ZipEntry> zipEntrys = readZipFile.getZipEntrys();
		if (zipEntrys.isEmpty()) {
			return;
		}
		for (ZipEntry zipEntry : zipEntrys) {
			String name = zipEntry.getName();
			String fileName = unZipFileNameFuction.apply(name);
			if (zipEntry.isDirectory()) {
				FileUtil.createDirectory(fileName);
			} else {
				File fileEntry = FileUtil.createNewFileOverride(fileName);
				ByteArraySupplier dataSupplier = zipEntry.getDataSource();
				byte[] data = dataSupplier.get();
				if (null != data) {
					FileUtils.writeByteArrayToFile(fileEntry, data);
				}
			}
		}
	}

	// ==================================================读取压缩文件==================================================

	@Override
	public ReadZipFile readZipFile(File file) throws IOException {
		org.apache.tools.zip.ZipFile antZipFile = buildZipFile(file);
		ReadZipFile readZipFile = new ReadZipFile(() -> {
			org.apache.tools.zip.ZipFile.closeQuietly(antZipFile);
		});
		@SuppressWarnings("unchecked")
		Enumeration<org.apache.tools.zip.ZipEntry> entries = antZipFile.getEntries();
		while (entries.hasMoreElements()) {
			org.apache.tools.zip.ZipEntry antZipEntry = entries.nextElement();
			String name = antZipEntry.getName();
			ZipEntry zipEntry = null;
			if (antZipEntry.isDirectory()) {
				zipEntry = new DirZipEntry(name);
			} else {
				zipEntry = new FileZipEntry(name, () -> {
					InputStream inputStream = antZipFile.getInputStream(antZipEntry);
					byte[] data = IOUtils.toByteArray(inputStream);
					inputStream.close();
					return data;
				});
			}
			readZipFile.addZipEntry(zipEntry);
		}
		return readZipFile;
	}

}
